﻿#region License

/*
 * Copyright © 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#endregion

#region Imports

using System;
using System.IO;

using IBatisNet.Common.Utilities;

using Spring.Core.IO;
using Spring.Objects.Factory.Config;

#endregion

namespace Spring.IBatis {
	/// <summary>
	/// Superclass providing common properties and a set of template methods to
	/// aid in the configuration of iBatis.NET
	/// <see cref="IBatisNet.DataMapper.SqlMapper"/> and
	/// <see cref="IBatisNet.DataAccess.DaoManager"/> instances.
	/// </summary>
	/// <author>Rick Evans</author>
	/// <version>$Id: AbstractIBatisFactoryObject.cs,v 1.1 2006/05/19 21:01:30 markpollack Exp $</version>
	public abstract class AbstractIBatisFactoryObject : AbstractFactoryObject {
		#region Constructor (s) / Destructor

		/// <summary>
		/// Creates a new instance of the <see cref="AbstractIBatisFactoryObject"/> class.
		/// </summary>
		/// <remarks>
		/// <p>
		/// This is an abstract class and as such has no publicly visible constructors.
		/// </p>
		/// </remarks>
		protected AbstractIBatisFactoryObject() {
		}

		#endregion

		/// <summary>
		/// Creates the iBatis.NET object.
		/// </summary>
		/// <exception cref="System.Exception">
		/// If an exception occured during object creation.
		/// </exception>
		/// <returns>The object returned by this factory.</returns>
		/// <seealso cref="Spring.Objects.Factory.Config.AbstractFactoryObject.GetObject()"/>
		protected override object CreateInstance() {
			if (ConfigLocation == null) {
				return CreateUsingDefaultConfig();
			} else {
				return CreateUsingCustomConfig();
			}
		}

		/// <summary>
		/// Template method to create and configure an iBatis.NET object
		/// using any default iBatis.NET configuration (file).
		/// </summary>
		/// <remarks>
		/// <p>
		/// The default iBatis.NET configuration file is named <c>SqlMap.config</c>.
		/// </p>
		/// </remarks>
		/// <returns>
		/// An iBatis.NET object using any default iBatis.NET configuration (file).
		/// </returns>
		protected abstract object CreateUsingDefaultConfig();

		/// <summary>
		/// Template method to create and configure an iBatis.NET object
		/// using the configured iBatis.NET configuration (file).
		/// </summary>
		/// <remarks>
		/// <p>
		/// The default iBatis.NET configuration file is named <c>SqlMap.config</c>.
		/// </p>
		/// </remarks>
		/// <returns>
		/// An iBatis.NET object using the configured iBatis.NET configuration (file).
		/// </returns>
		protected abstract object CreateUsingCustomConfig();

		/// <summary>
		/// Gets the name of an iBatis.NET configuration file.
		/// </summary>
		/// <returns>
		/// The name of an iBatis.NET configuration file.
		/// </returns>
		protected virtual string GetConfigFileName() {
			FileInfo configFile = null;
			try {
				configFile = ConfigLocation.File;
			} catch (IOException) {
				throw new ArgumentException(
						"The 'ConfigLocation' property cannot be resolved to an " +
						"iBatis.NET config file that physically exists on the filesystem.");
			}
			return configFile.Name;
		}

		#region Properties

		/// <summary>
		/// An iBatis.NET configuration (file) resource.
		/// </summary>
		/// <remarks>
		/// <p>
		/// If set, this must (currently) be an XML resource, typically something like
		/// <c>'sqlmap.config'</c> or <c>'dao.config'</c>. The resource can of course be
		/// pretty much anything (a file, an embedded resource, a URL, etc), but at the
		/// end of the day it must boil down to an XML document in the format of the
		/// iBatis.NET config file.
		/// </p>
		/// <p>
		/// May be <see langword="null"/>, in which case any default configuration will
		/// be used (typically <c>'sqlmap.config'</c> or <c>'dao.config'</c>, but you
		/// <b>will</b> want to consult the current iBatis.NET documentation about this).
		/// </p>
		/// </remarks>
		public IResource ConfigLocation {
			get { return configuration; }
			set { configuration = value; }
		}

		/// <summary>
		/// The <see cref="IBatisNet.Common.Utilities.ConfigureHandler"/> (if any)
		/// that will watch the <see cref="ConfigLocation"/> resource associated with the
		/// object created by this factory.
		/// </summary>
		/// <remarks>
		/// <p>
		/// May be <see langword="null"/>. If it is not <see langword="null"/>, the
		/// <see cref="ConfigLocation"/> resource <b>must</b> refer to a file resource on
		/// the filesystem (i.e. not embedded as an assembly resource, but a file
		/// that can be <i>watched</i> for changes).
		/// </p>
		/// </remarks>
		public ConfigureHandler ConfigWatcher {
			get { return configWatcher; }
			set { configWatcher = value; }
		}

		#endregion

		#region Fields

		private IResource configuration;
		private ConfigureHandler configWatcher;

		#endregion
	}
}
